<template>
	<view ref="bodywk" @click="hanlder" :class="[customClass, 'overflow']" :style="[
			computedHeight ? { height: computedHeight } : '', 
			computedWidth ? { width: computedWidth } : '',customCSSStyle]">
		<!-- #ifdef APP-NVUE -->
		<view v-if="isLoadEl" ref="nvueElAni" :animation="animationData" 
		
		:class="[
			'flex-col flex trani',
			animationName+reverseAniPrefxname,customClass
		]" >
			<slot name="default"></slot>
		</view>
		<!-- #endif -->
		<!-- #ifndef APP-NVUE -->
		<view v-if="isLoadEl" ref="nvueElAni"
		:style="{transitionDuration: `${props.duration}ms`,transitionTimingFunction:'ease'}"
		  :class="[
			'flex-col flex trani',
			animationClassName,
			customClass
		]" >
			<slot name="default"></slot>
		</view>
		<!-- #endif -->

	</view>
</template>

<script lang="ts" setup>
	/**
	 * 动画
	 * @description 提供了6组动画，并且每组件动画都支持反转播放，相当于12组动画了。可用于任何元素，进入场和出场的动画。
	 */
	import {
		getCurrentInstance,
		computed,
		ref,
		provide,
		inject,
		onMounted,
		onUnmounted,
		nextTick,
		watch
	} from 'vue';
	import {
		cssstyle,
		tmVuetify
	} from '../../tool/lib/interface';
	import {
		custom_props,
		computedClass,
		computedStyle
	} from '../../tool/lib/minxs';
	// #ifdef APP-PLUS-NVUE
	const Binding = uni.requireNativePlugin('bindingx');
	const dom = uni.requireNativePlugin('dom')
	const animation = uni.requireNativePlugin('animation')
	// #endif
	// 混淆props共有参数
	const props = defineProps({
		...custom_props,
		duration: {
			type: Number,
			default: 300
		},
		delay: {
			type: Number,
			default: 0
		},
		//动画名称
		name: {
			type: String,
			default: 'fade', //fade,left,right,up,down,zoom
		},
		autoPlay: {
			type: Boolean,
			default: true
		},
		disabled: {
			type: Boolean,
			default: false
		},
		height: {
			type: [Number, String],
			default: 0
		},
		width: {
			type: [Number, String],
			default: 0
		},
		//是否反向动画
		reverse: {
			type: [Boolean, String],
			default: false
		},
		//每变动一次，就重置动画一下，这个属性不对外，特殊情况使用。
		initByWechat:{
			type:Boolean,
			default:false
		}
	});
	const emits = defineEmits(['start', 'end', 'click']);

	function hanlder(e:any) {
		emits("click", e)
	}
	const proxy = getCurrentInstance()?.proxy??null;
	//自定义样式：
	const customCSSStyle = computed(() => computedStyle(props));
	//自定类
	const customClass = computed(() => computedClass(props));
	//高度，
	const computedHeight = computed(() => {
		if (!props.height || !Number(props.height)) {
			return 0
		}
		if (String(props.height).indexOf('px') > -1 || String(props.height).indexOf('rpx') > -1) {
			return String(props.height);
		}
		return String(props.height) + 'rpx';
	});

	// 宽度
	const computedWidth = computed(() => {
		if (!props.width) {
			return 0;
		}
		if (String(props.width).indexOf('px') > -1 || String(props.width).indexOf('rpx') > -1) {
			return props.width;
		}
		return props.width + 'rpx'
	})
	//动画名称
	const animationName = computed(() => props.name || "fade")
	//动画时长
	const durationtos = computed(() => props.duration)
	//是否反转。
	const computedReverse = computed(() => props.reverse)
	//反转动画前缀
	const reverseAniPrefxname = computed(() => computedReverse.value ? '-reverse' : '')
	//非nvue
	const animationClassName = ref(animationName.value+reverseAniPrefxname.value)
	//动画播放状态。0未开始,结束播放，1开始播放中,2结束。
	const animationStatus = ref(0)
	const tmid = ref(Number(uni.$tm.u.getUid(3)));
	//是否渲染完成。
	const isLoadEl = ref(false);
	//css3动画数据。
	const animationData = ref(null);
	watch([()=>props.initByWechat,()=>props.name],()=>{
		reset()
	})
	watch([()=>props.name],()=>{
		animationClassName.value = animationName.value+reverseAniPrefxname.value
		
	})
	function init() {
		nextTick(()=>{
			isLoadEl.value = true;
			if (props.autoPlay == true && !props.disabled) {
				nextTick(()=>play())
			}
		})
	}

	function play() {
		if (props.disabled == true) return;
		animationStatus.value = 0;
		// #ifdef APP-NVUE
		clearTimeout(tmid.value)
		nextTick(function() {
			tmid.value = setTimeout(function() {
				nvueAmatons();
			}, 50);
		})
		// #endif
		// #ifndef APP-PLUS-NVUE
		
		
		noNvueAmations();
		// #endif
	}

	function stop() {
		if (props.disabled == true) return;
		clearTimeout(tmid.value);
		animationStatus.value = 0;
		// noNvueAmationsReset()
	}

	function reset() {
		stop();
		
		animationStatus.value = 0;
	}
	//对外暴露方法。
	defineExpose({
		init: init,
		play: play,
		stop: stop,
		reset: reset
	})
	//获取当前播放状态。
	function getPlayStatus() {
		return animationStatus.value;
	}

	onMounted(() => init())
	onUnmounted(() => {
		clearTimeout(tmid.value);
		animationStatus.value = 0;
	})

	function nvueAmatons() {
		var el = proxy.$refs.nvueElAni;
		let propsAni = {};
		
		if (animationName.value == 'fade') {
			propsAni = {
				opacity:computedReverse.value?0:1,
				transformOrigin: 'center center'
			}
			
		} else if (animationName.value == 'up') {
			propsAni = {
				opacity:1,
				transform:computedReverse.value?'translateY(0%)':'translateY(-100%)',
				transformOrigin: 'center center'
			}

		} else if (animationName.value == 'down') {
			propsAni = {
				opacity:1,
				transform:computedReverse.value?'translateY(0%)':'translateY(100%)',
				transformOrigin: 'center center'
			}
		} else if (animationName.value == 'right') {
			propsAni = {
				opacity:1,
				transform:computedReverse.value?'translateX(0%)':'translateX(100%)',
				transformOrigin: 'center center'
			}
		} else if (animationName.value == 'left') {
			propsAni = {
				opacity:1,
				transform:computedReverse.value?'translateX(0%)':'translateX(-100%)',
				transformOrigin: 'center center'
			}
		} else if (animationName.value == 'zoom') {
			propsAni = {
				opacity:computedReverse.value?0:1,
				transform:computedReverse.value?'scale(0.7,0.7)':'scale(1,1)',
				transformOrigin: 'center center'
			}
		}
		emits('start');
		animationStatus.value = 1;
		clearTimeout(tmid.value)
		tmid.value = setTimeout(function() {
			animation.transition(el, {
				styles: propsAni,
				duration: props.duration, //ms
				timingFunction: 'ease',
				delay: 0//ms
			},()=>{
				emits('end');
				animationStatus.value = 2;
			})
		}, 20);
	}
	function noNvueAmations() {
		clearTimeout(tmid.value)
		// animationData.value = null;
		tmid.value = setTimeout(() => {
			if(computedReverse.value){
				animationClassName.value = animationName.value
			}else{
				animationClassName.value = animationName.value+ '-reverse'
			}
		}, 20);
		return ;
	}
</script>

<style scoped>

	.fade {
		opacity: 0;
		
	}
	.fade-reverse {
		opacity: 1;
	}

	.up {
		transform: translateY(0%);
	}

	.up-reverse {
		transform: translateY(-101%);
	}

	.down {
		transform: translateY(0%);
	}

	.down-reverse {
		transform: translateY(101%);
	}

	.left {
		transform: translateX(0%);
	}

	.left-reverse {
		transform: translateX(-101%);
	}

	.right {
		transform: translateX(0%);
	}

	.right-reverse {
		transform: translateX(101%);
	}

	.zoom {
		transform: scale(0.7, 0.7);
		opacity: 0;
	}

	.zoom-reverse {
		transform: scale(1, 1);
		opacity: 1;
	}

</style>
